#include "log.h"
#include <windowsx.h>
#include <tchar.h>
#include <commdlg.h>


Logger * lo;
#define max 10001
class Iterator 
{
public:  __int64 qwFileSize;
private:  DWORD dwBytesInBlock;
public:__int64 qwFileOffset;
public:  Iterator(__int64 qw,DWORD dw)
		 {
			 qwFileSize = qw;
			 dwBytesInBlock = dw;
		 }
public: void operator ++()
		{
		    qwFileOffset += dwBytesInBlock;
			qwFileSize-=dwBytesInBlock;
		}
public:bool operator >(int o)
	   {
		   if (qwFileSize>0)
			   return true;
		   else
			   return false;
	   }
public:bool operator <(int o)
	   {
		   if (qwFileSize<0)
			   return true;
		   else
			   return false;
	   }
public: DWORD value()
		{
			if (qwFileSize < dwBytesInBlock)
			{
				return (DWORD)qwFileSize; 
			}
			return dwBytesInBlock;
		}
};
int CharToMass(PBYTE pbFile,unsigned int a[],DWORD dwBytesInBlock,int x,bool*probel) 
{
	char s[7];
	int j = 0;
	int k=x;
	int t=0;
	bool first = false;
	if (x>-1)
	{
		first = true;
	}
	for (int i =0;i<dwBytesInBlock;i++)
	{
		if (pbFile[i] == ' ' )
		{
			if ((i==0)||(pbFile [i-1] != ' '))
			{
				s[j] = '\0';
				x = atoi(s);
				if (first)
				{
					first = false;
					t = 1;
					for (int y=0;y<j;y++)
					{
						t = t*10;
					}
					if ((t>1)&&(t+k>max))
					{
						return -3;
					}

					x = k * t + x;
				}			
				j=0;
				if (x>=max)
				{
					return -2;
				}
				a[x]++;
			}
			else
			{
				i++;
			}
			if ((i==0)&&((*probel)))
			{
				a[0] --;
				probel = false;
			}
		}
		else 
		{
			if ((pbFile[i]<'0')||(pbFile[i]>'9'))
			{
				return -4;
			}
			s[j] = pbFile[i];
			j++;
			if (j>6)
			{
				return -2;
			}
		}
	}

	if (pbFile[dwBytesInBlock-1]!=' ' )
	{
		s[j] = '\0';
		x = atoi(s);
		return x;
	}
	else
	{
		(*probel) = true;
	}
	return -1;
	
}
int MassToChar(PBYTE pbFile,unsigned int a[],DWORD dwBytesInBlock,int *i,int *o,int *j)//return >=0 if well done
{	
	char buffer [7];
	int pos=0;
	for ((*i);(*i)<max;(*i)++)
	{
		a[(*i)]-=(*o);
		if (a[(*i)] > 0)
		{
			itoa ((*i),buffer,10);
			for ((*o)=0;(*o)<a[(*i)];(*o)++)
			{
				while ((buffer[(*j)] != '\0')&&(pos < dwBytesInBlock))
				{
					pbFile[pos] = buffer[(*j)];
					pos++;
					(*j)++;
				}
				if (pos>=dwBytesInBlock)
				{
//					if (buffer[(*j)] == '\0')
//					{
//						(*o)++;
//					}
					return 0;
				}
				(*j)=0;
				pbFile[pos] = ' ';
				pos++;
			}
			(*o)=0;
			a[(*i)]=0;
		}
	}
	return 0;
}

int main (int argc,char* argv[])
{
	SYSTEM_INFO sinf;
	GetSystemInfo(&sinf); 
	lo = Logger::getInstance();
	(*lo).msg("Info","Begin");
	if (argc != 3)
	{
		(*lo).msg("Error","Wrong number of command");
		cout <<"argc  "<<argc<<endl;
		return 0;
	}
    wchar_t pszFileName[MAX_PATH]={0};
    wchar_t f2[MAX_PATH]={0};
    mbstowcs(pszFileName,argv[1],MAX_PATH);
    mbstowcs(f2,argv[2],MAX_PATH);
//	cout <<pszFileName<<endl;
//	cout <<f2<<endl;
	HANDLE hfile =  CreateFile(pszFileName, GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		(*lo).msg("Error","Can't create handle - wrong input file %s",argv[1]);
		cout <<"hfile"<<endl;
		return 0;
	}
	HANDLE mfile = CreateFileMapping(hfile,NULL,PAGE_READWRITE,0,0,NULL);
	if ((mfile == INVALID_HANDLE_VALUE)||(mfile == NULL))
	{
		(*lo).msg("Error","Can't create handle - wrong input file %s",argv[1]);
		return 0;
	}
	DWORD dwFileSizeHigh;
    __int64 qwFileSize = GetFileSize(hfile, &dwFileSizeHigh);
	__int64 size = qwFileSize;
	qwFileSize += (((__int64) dwFileSizeHigh) << 32); 
	Iterator it = Iterator (qwFileSize,sinf.dwAllocationGranularity*1024);
	CloseHandle(hfile);
    it.qwFileOffset = 0;
	unsigned int a[10001];
	if (qwFileSize > 4294967296)
	{
		(*lo).msg("Error","File is to big ");
		return 0;
	}
	for (int i =0;i<max;i++)
	{
		a[i]=0;
	}
	int x=-1;
	bool probel = false;
	clock_t t0 = clock();
	while (it > 0)
	{
        DWORD dw = it.value();
		PBYTE pbFile = (PBYTE)MapViewOfFile(mfile, FILE_MAP_READ,(DWORD) (it.qwFileOffset >> 32),(DWORD) (it.qwFileOffset & 0xFFFFFFFF),dw);
		x = CharToMass(pbFile,a,dw,x,&probel);
		if (x<-1)
		{
			if (x==-3)
			{
				(*lo).msg("Error","Wrong format of including input(3!!!!!!!!!!!) file %s",argv[1]);
			}
			(*lo).msg("Error","Wrong format of including input file %s",argv[1]);
			return 0;
		}
		UnmapViewOfFile(pbFile);
		it++;
    }
	CloseHandle(mfile);
	if (x>=0)
	{
		a[x]++;
	}
	clock_t t1 = clock();
//	cout << "time of reading: " << (double)(t1 - t0) / CLOCKS_PER_SEC<<" seconds" << endl;
	(*lo).msg("Info","End of reading file. Time = %f seconds ",(double)(t1 - t0) / CLOCKS_PER_SEC);
	it.qwFileOffset = 0;
	it.qwFileSize = size;
	it.qwFileSize += (((__int64) dwFileSizeHigh) << 32); 
	hfile = CreateFile(f2, GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		(*lo).msg("Error","Can't create handle of new file %s",argv[2]);
		return 0;
	}
	mfile = CreateFileMapping(hfile, NULL, PAGE_READWRITE, 0, it.qwFileSize, NULL); 
	if ((mfile == INVALID_HANDLE_VALUE)||(mfile == NULL))
	{
		(*lo).msg("Info","Can't creade mapping of new file %s",argv[2]);
		return 0;
	}
	x=0;
	int i=0;
	int j=0;
	int o=0;
	t0 = clock();
	while (it > 0) 
	{
		DWORD dw = it.value();
		PBYTE pbFile = (PBYTE)MapViewOfFile(mfile, FILE_MAP_WRITE,(DWORD) (it.qwFileOffset >> 32),(DWORD) (it.qwFileOffset & 0xFFFFFFFF),dw);
		x = MassToChar(pbFile,a,dw,&i,&o,&j);
		if (x<-1)
		{
			(*lo).msg("Fatal","Error in work of writing new file");
			return 0;
		}
		FlushViewOfFile(pbFile,dw);
		UnmapViewOfFile(pbFile);
		it++;
    }
	t1 = clock();

	(*lo).msg("Info","a[9999] = %d  o = %d ",a[9999],o);
//	cout << "time of writing: " << (double)(t1 - t0) / CLOCKS_PER_SEC<<" seconds" << endl;	
	(*lo).msg("Info","End of writeing in file. Time = %f seconds ",(double)(t1 - t0) / CLOCKS_PER_SEC);
	return 0;
}